<?php

namespace App\Http\Controllers\AdminApi;

use App\Models\VueAdmin as Admin;
use App\Helpers\Common;
use App\Exceptions\ParameterException;

use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use Exception;

class BaseController extends Controller
{
    const MSG_SUCCESS = '请求成功';
    const MSG_ERROR = '请求失败';
    const NOT_DATA = '暂无数据';
    const NOT_PARAM = '缺少参数';

    const STATUS_SUCCESS = 1;
    const STATUS_ERROR = 0;
    const STATUS_NOTICE = 2;
    const CODE_AUTHFAIL = 401;

    const SOURCE_UI_1 = 'element';
    const SOURCE_UI_2 = 'arco-design';

    protected $admin;
    protected $model; // 模型对象
    protected $modelName; // 模型名
    protected $defaultWhere = []; // Default where
    protected $defaultField = '*'; // Default field
    protected $defaultOrder = [['filed' => 'created_at', 'order' => 'desc']]; // Default order
    protected $primaryKey = 'id'; // primaryKey
    protected $columns = []; // columns

    protected $sourceUi = ''; // UI 框架

    public function __construct(Request $request)
    {
        $pathinfo = $request->path();
        $allowAction = ['adminapi/common/captcha', 'adminapi/common/setting'];
        if (!in_array($pathinfo, $allowAction)) {
            $this->middleware(['permission']);
        }
    }

    // 初始化
    public function initialize(Request $request)
    {
        $this->sourceUi = $request->header('sourceUi');

        $pathinfo = $request->route()->getName();
        $allowAction = ['adminapi/auth', 'adminapi/common/captcha', 'adminapi/common/setting', 'adminapi/setting/config'];
        if (in_array($pathinfo, $allowAction)) {
            return;
        }

        $token = $request->header('token');
        if (!$token) {
            $token = $request->input('token'); // 调试用
        }
        if ($token) {
            $jwt_data = \App\Services\AuthToken::verify($token);
            if ($jwt_data) {
                $admin = cache('auth_admin_id-' . $jwt_data->admin_id);

                $this->admin = $admin;
            }
        }
    }

    /**
     * List
     */
    public function list(Request $request)
    {
        $param = $request->all();

        $page = 1;
        $limit = 20;
        if (!empty($param['page'])) {
            $page = (int)$param['page'];
        }
        if (!empty($param['limit'])) {
            $limit = (int)$param['limit'];
        }
        $page = ($page - 1) * $limit;
        $sort_field = $param['sort_field'] ?? '';
        $sort_value = $param['sort_value'] ?? '';

        $className = '\\App\\Models\\' . $this->modelName;
        $model = new $className;
        $field = $this->defaultField;
        $orders = $this->defaultOrder;
        $where = $this->getFilterWhere($request);
        if ($this->defaultWhere) {
            $where = array_merge($this->defaultWhere, $where);
        }
        if ($sort_field && $sort_value) {
            $order[] = [
                'filed' => $sort_field,
                'order' => $sort_field
            ];
        }

        $query = $model->query();
        foreach ($where as $value) {
            $query->where($value[0], $value[1], $value[2]);
        }
        foreach ($orders as $order) {
            $query->orderBy($order['filed'], $order['order']);
        }
        $count = $query->count();
        $list = $query->take($limit)->skip($page)->get()->toArray();
        //dump($query->getQuery()->toSql());
        if ($list) {
            // 处理列表数据
            $list = $this->handleListData($list);
        }
        $data = [
            'data' => $list,
            'total' => $count
        ];

        return api_response(self::STATUS_SUCCESS, '', $data);
    }

    /**
     * Info
     */
    public function info(Request $request)
    {
        $param = $request->all();
        if (empty($param['id'])) {
            return api_response(self::STATUS_ERROR, self::NOT_PARAM, '');
        }

        $id = $param['id'];
        $className = '\\App\\Models\\' . $this->modelName;
        $model = new $className;
        $info = $model->find($id);
        if (!$info) {
            return api_response(self::STATUS_ERROR, '不存在！', []);
        }
        $info = $model->formatItem($info, ['format_source' => 'backend']);

        return api_response(self::STATUS_SUCCESS, '', $info);
    }

    /**
     * Save
     */
    public function save(Request $request)
    {
        DB::beginTransaction();
        try {
            $className = '\\App\\Models\\' . $this->modelName;
            $model = new $className;

            $data = $this->evalData($request);
            if (isset($data['id']) && $data['id']) {
                $info = $model->where('id', $data['id'])->select(['*'])->first();
                if (!$info) {
                    DB::rollback();
                    return api_response(self::STATUS_ERROR, '不存在', '');
                }
                $data['updated_at'] = time();
                $message = '保存失败';
                $result = $model->where('id', $data['id'])->update($data);

                $afterAction = '_after_update';
            } else {
                $data['created_at'] = time();
                $message = '创建失败';
                $result = $model->create($data);
                $data['id'] = $result->id ?? 0;

                $afterAction = '_after_insert';
            }
            if ($result === false) {
                DB::rollback();
                return api_response(self::STATUS_ERROR, $message, []);
            }

            // Query执行后的操作
            $model->$afterAction($data);
            if (isset($info)) {
                $afterRes = $this->afterUpdate($data, $info);
            } else {
                $afterRes = $this->afterInsert($data);
            }
            if ($afterRes['code'] != 1) {
                DB::rollback();
                return api_response(self::STATUS_ERROR, $afterRes['msg'] ?? 'after error', []);
            }

            DB::commit();
            return api_response(self::STATUS_SUCCESS, self::MSG_SUCCESS, $data);
        } catch (Exception $e) {
            DB::rollBack();
            return api_response(self::STATUS_ERROR, '失败', $e->getMessage());
        }
    }

    /**
     * Delete
     */
    public function delete(Request $request)
    {
        $param = $request->all();
        if (empty($param['id']) && empty($param['ids'])) {
            return api_response(self::STATUS_ERROR, self::NOT_PARAM, '');
        }

        DB::beginTransaction();
        try {
            $className = '\\App\\Models\\' . $this->modelName;
            $model = new $className;
            if (isset($param['ids']) && $param['ids']) {
                $ids = (array)$param['ids'];
            } else {
                $ids = (array)$param['id'];
            }
            foreach ($ids as $id) {
                $info = $model->where('id', $id)->select(['*'])->first();
                if (!$info) {
                    DB::rollBack();
                    return api_response(self::STATUS_ERROR, '不存在', '');
                }
                if (method_exists($model, 'isUsed')) {
                    // 是否被使用
                    $usedInfo = $model->isUsed($id);
                    if ($usedInfo['code'] == 0) {
                        DB::rollBack();
                        return api_response(self::STATUS_ERROR, $usedInfo['msg'], '');
                    }

                    if ($usedInfo['code'] == 1) {
                        //$result = $info->delete();
                        $result = $model->doDelete($id);
                    } elseif ($usedInfo['code'] == 2) {
                        $info->status = 90;
                        $result = $info->save();
                    }
                } else {
                    //$result = $info->delete();
                    $result = $model->doDelete($id);
                }
                if ($result === false) {
                    DB::rollBack();
                    return api_response(self::STATUS_ERROR, 'Error', '');
                }

                // Query执行后的操作
                $model->_after_delete($info ?? $id);
                $afterRes = $this->afterDelete($info ?? ['id' => $id]);
                if ($afterRes['code'] != 1) {
                    return api_response(self::STATUS_ERROR, $afterRes['msg'] ?? 'after error', []);
                }
            }

            DB::commit();
            return api_response(self::STATUS_SUCCESS, self::MSG_SUCCESS, '');
        } catch (Exception $e) {
            DB::rollBack();
            return api_response(self::STATUS_ERROR, '失败', $e->getMessage());
        }
    }

    /**
     * 操作
     */
    public function handle(Request $request)
    {
        $param = $request->all();
        if (empty($param['id']) && empty($param['ids'])) {
            return api_response(self::STATUS_ERROR, self::NOT_PARAM, '');
        }
        if (!isset($param['status'])) {
            return api_response(self::STATUS_ERROR, '操作类型(status)不能为空', self::NOT_PARAM);
        }

        DB::beginTransaction();
        try {
            $className = '\\App\\Models\\' . $this->modelName;
            $model = new $className;
            if (isset($param['ids']) && $param['ids']) {
                $ids = (array)$param['ids'];
            } else {
                $ids = (array)$param['id'];
            }
            foreach ($ids as $id) {
                $info = $model->where('id', $id)->select(['*'])->first();
                if (!$info) {
                    DB::rollBack();
                    return api_response(self::STATUS_ERROR, '不存在', '');
                }
                if ($param['status'] == 90) {
                    if (method_exists($model, 'isUsed')) {
                        // 是否被使用
                        $usedInfo = $model->isUsed($id);
                        if ($usedInfo['code'] == 0) {
                            DB::rollBack();
                            return api_response(self::STATUS_NOTICE, $usedInfo['msg'], '');
                        }

                        if ($usedInfo['code'] == 1) {
                            $result = $info->delete();
                        } elseif ($usedInfo['code'] == 2) {
                            $info->status = 90;
                            $result = $info->save();
                        }
                    } else {
                        //$result = $info->delete();
                        $result = $model->doDelete($id);
                    }
                } else {
                    $info->status = $param['status'];
                    $result = $info->save();
                }
                if ($result === false) {
                    DB::rollBack();
                    return api_response(self::STATUS_ERROR, '失败', '');
                }

                $param['id'] = $id;
                $afterRes = $this->afterHandle($param, $info);
                if ($afterRes['code'] != 1) {
                    DB::rollback();
                    return api_response(self::STATUS_ERROR, $afterRes['msg'] ?? 'after error', []);
                }
            }

            DB::commit();
            return api_response(self::STATUS_SUCCESS, self::MSG_SUCCESS, '');
        } catch (Exception $e) {
            DB::rollBack();
            return api_response(self::STATUS_ERROR, '失败', $e->getMessage());
        }
    }

    /**
     * 更新排序
     */
    public function listOrders(Request $request)
    {
        $param = $request->all();
        if (empty($param['ids'])) {
            return api_response(self::STATUS_ERROR, 'ID(ids)不能为空', self::NOT_PARAM);
        }
        if (!isset($param['sorting'])) {
            return api_response(self::STATUS_ERROR, '排序值(sorting)不能为空', self::NOT_PARAM);
        }

        DB::beginTransaction();
        try {
            $ids = (array)$param['ids'];
            $sortField = 'sorting';
            $fields = (array)$param[$sortField];
            $className = '\\App\\Models\\' . $this->modelName;
            $model = new $className;

            $result = true;
            foreach ($ids as $key => $id) {
                $data[$sortField] = $fields[$key];
                $res = $model->where('id', $id)->update($data);
                if ($res === false) {
                    $result = false;
                    break;
                }
            }
            if ($result === false) {
                DB::rollBack();
                return api_response(self::STATUS_ERROR, '失败', '');
            }

            DB::commit();
            return api_response(self::STATUS_SUCCESS, self::MSG_SUCCESS, '');
        } catch (Exception $e) {
            DB::rollBack();
            return api_response(self::STATUS_ERROR, '失败', $e->getMessage());
        }
    }

    /**
     * 检查名称是否已存在
     */
    public function checkName(Request $request)
    {
        $param = $request->all();
        if (empty($param['name'])) {
            return api_response(self::STATUS_ERROR, self::NOT_PARAM, '');
        }

        $name = $param['name'];
        $className = '\\App\\Models\\' . $this->modelName;
        $model = new $className;
        $info = $model->where('name', $name)->where('status', '<>', 90)->select(['id'])->first();
        if (!$info) {
            return api_response(0, '不存在！', []);
        }
        return api_response(1, '存在！', []);
    }

    /**
     * Eval data for post data save
     *
     * @param Request $request
     * @return array
     */
    protected function evalData($request)
    {
        $data = $request->all();

        unset($data['created_at'], $data['updated_at'], $data['_token'], $data['s']);
        // 去掉文件上传字段file
        unset($data['file']);

        return $data;
    }

    /**
     * 处理列表数据
     */
    protected function handleListData($data)
    {
//        $className = '\\App\\Models\\' . $this->modelName;
//        $model = new $className;
//
//        $data = $model->formatDatas($data, ['format_source' => 'backend']);

        return $data;
    }

    /**
     * 筛选条件
     */
    protected function getFilterWhere($request)
    {
        $where = [];

        return $where;
    }

    /**
     * 默认条件
     */
    protected function getDefaultWhere()
    {
        $defaultWhere = [
            //['status', '<>', 90] // model 全局的查询范围
        ];

        return $defaultWhere;
    }

    protected function afterInsert($data)
    {
        // 写入日志
        $content = '添加了一条' . __('common.' . $this->modelName) . '数据。';
        $logRes = Common::actionLog(request(), $this->admin['id'], $content, $data['id'], json_encode([$data]));
        if ($logRes === false) {
            return ['code' => 0, 'msg' => '写入日志失败'];
        }

        return ['code' => 1, 'msg' => ''];
    }

    protected function afterUpdate($data, $info = [])
    {
        // 写入日志
        $content = '更新了一条' . __('common.' . $this->modelName) . '数据。';
        $logRes = Common::actionLog(request(), $this->admin['id'], $content, $data['id'], json_encode([$data, $info]));
        if ($logRes === false) {
            return ['code' => 0, 'msg' => '写入日志失败'];
        }

        return ['code' => 1, 'msg' => ''];
    }

    protected function afterDelete($data)
    {
        // 写入日志
        $content = '删除了一条' . __('common.' . $this->modelName) . '数据。';
        $logRes = Common::actionLog(request(), $this->admin['id'], $content, $data['id'], json_encode([$data]));
        if ($logRes === false) {
            return ['code' => 0, 'msg' => '写入日志失败'];
        }

        return ['code' => 1, 'msg' => ''];
    }

    protected function afterHandle($data, $info = [])
    {
        // 写入日志
        $content = '操作了一条' . __('common.' . $this->modelName) . '数据。';
        $logRes = Common::adminLog(request(), $this->admin['id'], $content, $data['id'], json_encode([$data, $info]));
        if ($logRes === false) {
            return ['code' => 0, 'msg' => '写入日志失败'];
        }

        return ['code' => 1, 'msg' => ''];
    }
}
